﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Accountant.MySerializer;
using System.Linq;

namespace Accountant.DataModel
{
  public class Database
  {
    private readonly string _basePath;
    private static Action<DbContext> _initializeDatabase;

    public Database(string basePath)
    {
      _basePath = basePath;
    }

    public void SetInitializer<TContext>(IDatabaseInitializer<TContext> initializer) 
      where TContext : DbContext
    {
      _initializeDatabase = c => initializer.InitializeDatabase((TContext)c);
    }
    public bool Exists {  get { return Directory.Exists(_basePath); } }
    public void Delete() {  if (Exists) Directory.Delete(_basePath, true); }

    internal void InitializeDatabase(DbContext accountantContext)
    {
      if (_initializeDatabase != null) _initializeDatabase(accountantContext);
    }

    public IEnumerable<string> GetChunks(string tableName)
    {
      return Directory.EnumerateFiles(_basePath, tableName + "!*.bin");
    }
    public BinaryReader OpenChunkRead(string chunk)
    {
      return new BinaryReader(File.Open(chunk, FileMode.Open), Encoding.UTF8);
    }

    public IEnumerable<Chunk> BrakeToChunks<T>(string tableName, IList<T> transactions)
    {
      yield return new Chunk(Path.Combine(_basePath, tableName + "!1.bin"), 0, transactions.Count);
    }

    public BinaryWriter OpenChunkWrite(string chunk)
    {
      return new BinaryWriter(File.Open(chunk, FileMode.Create), Encoding.UTF8);
    }

    public TextWriter CreateDump()
    {
      return File.CreateText(Path.Combine(_basePath, "dump.txt"));
      
    }
    public class Chunk
    {
      public string FileName { get; private set; }
      public int From { get; private set; }
      public int To { get; private set; }

      public Chunk(string fileName, int from, int to)
      {
        FileName = fileName;
        From = from;
        To = to;
      }
    }

    public void Create()
    {
      Directory.CreateDirectory(_basePath);
    }

    public long GetSize()
    {
      return Directory.GetFiles(_basePath, "*.*", SearchOption.AllDirectories)
        .Sum(path => new FileInfo(path).Length);
    }
  }
}